/*
 *  Copyright (C) 2011  Clint Priest
 *
 *  This file is part of pklib.
 *
 *  pklib is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  pklib is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with pklib.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Portions borrowed or re-written from prototype
 */

var XulPanel = Class.create( {
	Top: { 
		get: function() { return this._Top || this.Window.boxObject.screenY; },
		set: function(y) { 
			this._Top = y;
			this.Window.top = y;
//			this.Window.AlterStyleAttribute( { top: y + 'px' } );
//			y = Math.max(y, 0);
//			y = Math.min(y, this.Document.documentElement.clientHeight - 10);
			/*this.Window.top = y;*/
//			console.log('top: %s/%s', y, this.Window.style.top);
		},
	},
	Left: { 
		get: function() { return this._Left || this.Window.boxObject.screenX; },
		set: function(x) { 
			this._Left = x;
			this.Window.left = x;
//			this.Window.AlterStyleAttribute( { left: x + 'px' } );
//			x = Math.max(x, 10 - this.Width);
//			x = Math.min(x, this.Document.documentElement.clientWidth - 10);
			/*this.Window.left = x;*/
//			console.log('left: %s/%s', x, this.Window.left);
		},
	},
	Width: { 
		get: function() { return this._Width || this.Window.boxObject.width; },
		set: function(x) { 
			this._Width = x;
			this.Window.AlterStyleAttribute( { width: x + 'px' } );
			/*this.Window.width = Math.max(x, 75) + 'px';*/ 
		},
	},
	Height: { 
		get: function() { return this._Height || this.Window.boxObject.height; },
		set: function(y) { 
			this._Height = y;
			this.Window.AlterStyleAttribute( { height: y + 'px' } );
			/*this.Window.height = Math.max(y, 25) + 'px';*/ 
		},
	},
	WindowPosition: {
		get: function() {
			return { 
				top: 	this.Top,
				left: 	this.Left,
				bottom: this.Top + this.Height, 
				right: 	this.Left + this.Width,
				width: 	this.Width,
				height: this.Height,
			};
		},
		set: function(x) {
			if(x.top)
				this.Top = x.top;
			if(x.left) 
				this.Left = x.left;
			if(x.width)
				this._Width = x.width;
			if(x.height)
				this._Height = x.height;
			this.Window.AlterStyleAttribute( { width: this._Width+'px', height: this._Height+'px' });
			this.OnResize(new Rect(this.Top, this.Left, this.Top + this.Height, this.Left + this.Width));
		}
	},
	
	Visible: { 
		get: function() { return this.style.display != 'none'; },
		set: function(x) { this.style.display = (x ? 'block' : 'none'); },
	},
	
	Title: { 
		get: function() { return this.TitlebarElement.getAttibute('value'); },
		set: function(x) { this.TitlebarElement.setAttribute('value', x); },
	},
	
	initialize: function(XulTemplate) {
		this.Document = $doc();

		XulTemplate = XulTemplate || File.GetContents('chrome://SnapGraph/content/pklib/chrome/XulWindow.xul');
		this.Window = CreateAnonymousElement(XulTemplate);
		
		this.TitlebarElement = this.Window.down('.Titlebar');
		this.TitlebarElement.Closer = this.Window.down('.Closer');
		this.TitlebarElement.hide = function(hide) {
			var cs = window.getComputedStyle(this);
			if(hide) {
				this.HideTimeoutID = setTimeout(function() {
					if(cs.opacity != 0) {
						this.animate( { opacity: 0 }, 500 );
						this.Closer.animate( { opacity: 0 }, 500);
					}
				}.bind(this), 2000);
			} else {
				clearTimeout(this.HideTimeoutID);
				if(cs.opacity != 1) {
					this.animate( { opacity: 1 }, 200 );
					this.Closer.animate( { opacity: 1 }, 200 );
				}
			}
		}
		this.TitlebarElement.addEventListener('mouseover', this.TitlebarElement.hide.bind(this.TitlebarElement, false), true);
		this.TitlebarElement.addEventListener('mouseout', this.TitlebarElement.hide.bind(this.TitlebarElement, true), true);

		this.TitlebarElement.hide(true);
		
		this.ContentElement = this.Window.down('#content');	
		document.getElementById('tab-view-deck').appendChild(this.Window);
		
		this.WindowMoving = false;
		this.WindowResizing = false;
		this.Window.addEventListener('mousedown', this.OnMouseDown.bind(this), false);
		this._OnMouseMove = this.OnMouseMove.bind(this);
		this.Window.addEventListener('mouseup', this.OnMouseUp.bind(this), false);
	},
	
	show: function(x, y) {
		this.Window.openPopup(null, '', x || 100, y || 100, false, false);
	},
	OnMouseDown: function(e) {
		this.domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
									.getInterface(Components.interfaces.nsIDOMWindowUtils);
									
		var elem = e.originalTarget;
		var Behavior = elem.getAttribute('Behavior');
		if(Behavior) {
			if(Behavior.toLowerCase().indexOf('resize') != -1) {
				/* I don't know why this next line is necessary, 
					but ResizeSW does not work properly without it until the Top/Left has been set once */
				this.Top = this.Top;  this.Left = this.Left;
				
				this.ResizeBehavior = Behavior.replace(/resize/i, '');
				this.WindowResizing = true;
				this.MouseDragOffset = { x: e.screenX - this.Left, y: e.screenY - this.Top, ix: this.Width - (e.screenX - this.Left), iy: this.Height - (e.screenY - this.Top)};
				this.StartMouseTracking(e);
			} else {
				switch(Behavior.toLowerCase()) {
					case 'movewindow':
						this.WindowMoving = true;
						this.MouseDragOffset = { x: e.clientX - this.Left, y: e.clientY - this.Top };
						this.StartMouseTracking(e);
						break;
					case 'closewindow':
						if(this.OnClose() != false)
							this.Window.hidePopup();
						break;
					
				}
			}
		}
	},
	OnMouseMove: function(e) {
		this.domWindowUtils.suspendTimeouts();
		try {
			if(this.WindowMoving) {
				this.Top = e.clientY - this.MouseDragOffset.y;
				this.Left = e.clientX - this.MouseDragOffset.x;
				e.preventDefault();
			} else if(this.WindowResizing) {
				var StartWindowPosition = this.WindowPosition;
				var EndWindowPosition = StartWindowPosition;
				
				switch(this.ResizeBehavior) {
					case 'NW':
						
						EndWindowPosition.top = e.screenY - this.MouseDragOffset.y;
						EndWindowPosition.left = e.screenX - this.MouseDragOffset.x;
						EndWindowPosition.width = StartWindowPosition.right - EndWindowPosition.left;
						EndWindowPosition.height = StartWindowPosition.bottom - EndWindowPosition.top;
						break;
					case 'NE':
						EndWindowPosition.width = (e.screenX - EndWindowPosition.left) + this.MouseDragOffset.ix;
						EndWindowPosition.top = e.screenY - this.MouseDragOffset.y;
						EndWindowPosition.height = StartWindowPosition.bottom - EndWindowPosition.top;
						break;
					case 'SE':
						EndWindowPosition.width = (e.screenX - EndWindowPosition.left) + this.MouseDragOffset.ix;
						EndWindowPosition.height = (e.screenY - EndWindowPosition.top) + this.MouseDragOffset.iy;
						break;
					case 'SW':
						EndWindowPosition.left = e.screenX - this.MouseDragOffset.x;
						EndWindowPosition.width = StartWindowPosition.right - EndWindowPosition.left;
						EndWindowPosition.height = (e.screenY - EndWindowPosition.top) + this.MouseDragOffset.iy;
						break;
					case 'N':
						EndWindowPosition.top = e.screenY - this.MouseDragOffset.y;
						EndWindowPosition.height = StartWindowPosition.bottom - EndWindowPosition.top;
						break;
					case 'E':
						EndWindowPosition.width = (e.screenX - EndWindowPosition.left) + this.MouseDragOffset.ix;
						break;
					case 'S':
						EndWindowPosition.height = (e.screenY - EndWindowPosition.top) + this.MouseDragOffset.iy;
						break;
					case 'W':
						EndWindowPosition.left = e.screenX - this.MouseDragOffset.x;
						EndWindowPosition.width = StartWindowPosition.right - EndWindowPosition.left;
						break;
				}
				this.WindowPosition = EndWindowPosition;
				e.preventDefault();
			}
		} finally {
			this.domWindowUtils.resumeTimeouts();
			this.domWindowUtils.processUpdates();
		}
	},
	OnMouseUp: function(e) {
		if(this.WindowMoving) {
			this.WindowMoving = false;
			this.StopMouseTracking(e);
		}
		if(this.WindowResizing) {
			this.WindowResizing = false;
			this.StopMouseTracking(e);
		}
		
		this.Window.removeEventListener('mousemove', this._OnMouseMove, false);
	},
	StartMouseTracking: function(e) {
		this.Window.setCapture(true);
		this.Window.addEventListener('mousemove', this._OnMouseMove, false);
		e.preventDefault();
	},
	StopMouseTracking: function(e) {
		e.preventDefault();
		this.Window.releaseCapture();
	},
	
	/* Called when the close button was pressed */
	OnClose: function() { return true; },
	OnResize: function(r) { },
} );